/*
 *
 *  File: 'SPCounter.h'
 *
 *  Author: Samip Shah <samipshah@alumni.cmu.edu>
 *  Date: Sep 11, 2011
 *
 */

#ifndef SPCOUNTER_H
#define SPCOUNTER_H

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <string.h>

template<typename T>
class SPCounter {
	T* limits;
	int limitsSize;

	T* cntlimit;
	int cntlimitSize;

	public:
		SPCounter(T* lim, int cnt) {
			limits = new T[cnt];
			memcpy(limits, lim, cnt);
			limitsSize = cnt;
		}

		~SPCounter() {
			delete [] limits;
			delete [] cntlimit;
		}

		void printData() {
			for(int i =0; i < limitsSize; i++) {
				std::cout << (int)limits[i] << ", ";	
			}
			std::cout << std::endl;
			for(int i=0 ; i < cntlimitSize; i++) {
				std::cout << (int)cntlimit[i] << ", ";
			}
			std::cout << std::endl;
		}

		void setIndexes(T* mask, int cnt) {
			cntlimitSize = cnt;
			cntlimit = new T[cnt];
			for(int i=0 ; i <cnt; i++){
				if(mask[i] > limitsSize) {
					fprintf(stderr, 
						"Some Serious Error\n");
					exit(-1);
				}

				cntlimit[i] = limits[mask[i]];
			}
		}

		bool next(T* cnt) {
			static int lcnt =0;
			
			if(!lcnt) {
				memset(cnt, 0, cntlimitSize);
				lcnt++;
				return true;
			}

			bool chkequality = true;
			for(int i =0; i < cntlimitSize; i++){
				if(cnt[i] != cntlimit[i]) {
					chkequality = false;
					break;
				}
			}

			if(chkequality) {
				return false;
			}
			
			for(int j=(cntlimitSize-1); j >= 0 ; j-- ) {
				if(cnt[j] == cntlimit[j])
					continue;

				cnt[j]++;
				for(int i=j+1 ; i< cntlimitSize; i++)
					cnt[i] = 0;
				break;
			}

			return true;
		}
};

#endif
